home *** CD-ROM | disk | FTP | other *** search
- Path: unix.sri.com!usenet
- From: mklenk@updike.sri.com (Mark Klenk)
- Newsgroups: comp.lang.c
- Subject: Re: garbage collection and C (not C++!)
- Date: 26 Jan 1996 22:14:22 GMT
- Organization: SRI International
- Message-ID: <4ebjnu$424@unix.sri.com>
- References: <4e4bc5$c5f@ns.RezoNet.NET>
- Reply-To: mklenk@updike.sri.com
- NNTP-Posting-Host: 204.75.161.40
-
-
- Ray Dunn:
- >
- >I think we'd all be interested in this. Post it.
-
- Ok, you asked for it - here it is.
-
- --- gc.h ---
- /*
- * FILE: gc.h LANGUAGE: ANSI C
- *
- * AUTHOR: Mark Klenk DATE: 12/22/94
- *
- * PURPOSE: Definition of a garbage collection interface.
- */
-
- #ifndef __GC_H__
- #define __GC_H__
-
- #include <stdlib.h> /* size_t */
-
- #ifndef GC_DISABLE
- #define malloc(size) gc_malloc(size)
- #define calloc(num, size) gc_calloc(num, size)
- #define realloc(ptr, size) gc_realloc(ptr, size, __FILE__, __LINE__)
- #define free(ptr) gc_free(ptr, __FILE__, __LINE__)
- #endif
-
- void * gc_malloc (size_t size);
- void * gc_calloc (size_t num, size_t size);
- void * gc_realloc (void * ptr, size_t size, char const * filename, int line);
- void gc_free (void * ptr, char const * filename, int line);
-
- #endif
-
- --- gc.c ---
- /*
- * FILE: gc.c LANGUAGE: ANSI C
- *
- * AUTHOR: Mark Klenk DATE: 12/22/94
- *
- * PURPOSE: Implementation of a garbage collection interface.
- */
-
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include "gc.h"
-
- #undef malloc
- #undef calloc
- #undef realloc
- #undef free
-
-
- typedef struct _GC_Node GC_Node;
-
- struct _GC_Node {
- GC_Node * next;
- void * ptr;
- size_t size;
- };
-
-
- static GC_Node gc_heap = {NULL, NULL, 0};
-
-
- static void gc_exit_cleanup(void)
- {
- GC_Node * curr;
-
- while ((curr = gc_heap.next) != &gc_heap) {
- gc_heap.next = curr->next;
- free(curr->ptr);
- free(curr);
- }
- }
-
-
- static void gc_signal_handler(int signal_no)
- {
- signal(SIGINT, gc_signal_handler); /* Make sure we catch another CTRL-C. */
- gc_exit_cleanup();
- signal(SIGINT, SIG_DFL); /* Restore the interrupt handler. */
- raise(signal_no); /* Wake up default handler. */
- }
-
-
- static void gc_initialize(void)
- {
- if (NULL == gc_heap.next) {
- gc_heap.next = &gc_heap;
- atexit(gc_exit_cleanup);
- signal(SIGINT, gc_signal_handler);
- signal(SIGABRT, gc_signal_handler);
- }
- }
-
-
- static GC_Node * gc_find_node(void * ptr)
- {
- GC_Node * prev;
-
- for (prev = &gc_heap; prev->next != &gc_heap; prev = prev->next) {
- if (prev->next->ptr == ptr) {
- return prev;
- }
- }
-
- return NULL;
- }
-
-
- static void gc_error(void * ptr, char const * filename, int line)
- {
- fprintf(stderr, "Garbage collector caught invalid pointer %p in %s: %d.\n",
- ptr, filename, line);
- abort();
- }
-
-
- void * gc_malloc(size_t size)
- {
- GC_Node * node;
-
- gc_initialize();
-
- node = malloc(sizeof(GC_Node));
- if (NULL == node) {
- return NULL;
- }
-
- node->ptr = malloc(size);
- if (NULL == node->ptr) {
- free(node);
- return NULL;
- }
-
- node->size = size;
- node->next = gc_heap.next;
- gc_heap.next = node;
-
- return node->ptr;
- }
-
-
- void * gc_calloc(size_t num, size_t size)
- {
- GC_Node * node;
-
- gc_initialize();
-
- node = malloc(sizeof(GC_Node));
- if (NULL == node) {
- return NULL;
- }
-
- node->ptr = calloc(num, size);
- if (NULL == node->ptr) {
- free(node);
- return NULL;
- }
-
- node->size = size * num;
- node->next = gc_heap.next;
- gc_heap.next = node;
-
- return node->ptr;
- }
-
-
- void * gc_realloc(void * ptr, size_t size, char const * filename, int line)
- {
- GC_Node * node;
-
- gc_initialize();
-
- if (NULL == ptr) {
- return gc_malloc(size); /* Create it if it doesn't exist. */
- }
-
- node = gc_find_node(ptr);
- if (NULL == node) {
- gc_error(ptr, filename, line); /* This means 'ptr' is invalid. */
- }
- node = node->next; /* Point to actual node, not prev. */
-
- ptr = realloc(ptr, size);
- if (NULL == ptr) {
- return NULL;
- }
-
- node->ptr = ptr;
- node->size = size;
-
- return ptr;
- }
-
-
- void gc_free(void * ptr, char const * filename, int line)
- {
- GC_Node * curr;
- GC_Node * prev;
-
- gc_initialize();
-
- if (NULL == ptr) {
- return;
- }
-
- prev = gc_find_node(ptr);
- if (NULL == prev) {
- gc_error(ptr, filename, line); /* This means 'ptr' is invalid. */
- }
-
- curr = prev->next;
- prev->next = curr->next;
-
- free(curr->ptr);
- free(curr);
- }
-
-
-
- ---
-
- mklenk@coronacorp.com (Mark Klenk)
-
-
-
-